home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_01_03 / 1n03073a < prev    next >
Text File  |  1990-07-08  |  16KB  |  675 lines

  1. /*
  2.     Screen
  3.         2.50
  4.         19-Jun-1990
  5.         ANSI C for MS-DOS w/monochrome or color text
  6.         display
  7.  
  8.         Provides a set of functions for manipulating a
  9.         text display. To drastically improve the speed
  10.         of this module, NO RANGE CHECKING is done!
  11.         Invalid line/column values may cause portions
  12.         of non-video memory to be corrupted!
  13.  
  14.         Written by Scott Robert Ladd. Released into
  15.         the public domain.
  16. */
  17.  
  18. #include "conio.h"
  19. #include "dos.h"
  20. #include "screen.h"
  21. #include "stdarg.h"
  22. #include "stdio.h"
  23. #include "stdlib.h"
  24. #include "string.h"
  25.  
  26. static ScrType      VideoType    = ST_UNKNOWN;
  27. static ScrMode      VideoMode    = SM_UNKNOWN;
  28. static ScrMode      OriginalMode = SM_UNKNOWN;
  29. static ScrAccess    AccessMode   = SA_DIRECT;
  30. static unsigned int Width        = 0;
  31. static unsigned int Length       = 0;
  32. static unsigned int BaseAdr      = 0;
  33. static unsigned int CursorShape  = 0;
  34. static int          CursorHidden = 0;
  35. static int *        SavedScreen  = NULL;
  36. static unsigned int SavedCursPos = 0;
  37. static int          SavedCursShp = 0;
  38. static union REGS   regs;
  39.  
  40. #if !defined(MK_FP)
  41.     #define MK_FP(seg,off) (void far *)(((long)/
  42.             (seg) << 16L) | (long)(off))
  43. #endif
  44.  
  45. ScrType ScrOpen(void)
  46.     {
  47.     int i, status_changed;
  48.     unsigned char orig_status;
  49.     int far * vmemptr;
  50.  
  51.     /* Attempt to identify the type of video adapter installed.
  52.        Call VGA "Identify Adapter Service" first */
  53.  
  54.     regs.h.ah = 0x1A;
  55.     regs.h.al = 0;
  56.     int86(0x10,®s,®s);
  57.  
  58.     if (regs.h.al == 0x1A)
  59.         {
  60.         switch (regs.h.bl)
  61.             {
  62.             case 1 :
  63.                 VideoType = ST_MDA;
  64.                 break;
  65.  
  66.             case 2 :
  67.                 VideoType = ST_CGA;
  68.                 break;
  69.  
  70.             case 4 :
  71.             case 5 :
  72.                 VideoType = ST_EGA;
  73.                 break;
  74.  
  75.             case 7 :
  76.             case 8 :
  77.                 VideoType = ST_VGA;
  78.                 break;
  79.  
  80.             case 10:
  81.             case 11:
  82.             case 12:
  83.                 VideoType = ST_MCGA;
  84.                 break;
  85.  
  86.             default:
  87.                 return 1;
  88.             }
  89.         }
  90.     else
  91.         {
  92.         /* VGA services not available -- maybe it's EGA */
  93.  
  94.         regs.h.ah = 0x12;
  95.         regs.x.bx = 0x0010;
  96.         int86(0x10,®s,®s);
  97.  
  98.         /* if BX is 0x10, we have an EGA */
  99.  
  100.         if (regs.x.bx != 0x10)
  101.             VideoType = ST_EGA;
  102.         else
  103.             {
  104.             /* check two-bit "monitor type" setting in equipment word */
  105.  
  106.             int86(0x11,®s,®s);
  107.  
  108.             switch ((regs.h.al & 0x30) >> 4)
  109.                 {
  110.                 case 0 :
  111.                     return 1;
  112.  
  113.                 case 1 :
  114.                 case 2 :
  115.                     VideoType = ST_CGA;
  116.                     break;
  117.  
  118.                 case 3 :
  119.                     /* if we have a mono adapter, a Hercules can be
  120.                        differentiated from an MDA by seeing if the high bit
  121.                        of the status register changes */
  122.  
  123.                     status_changed = 0;
  124.  
  125.                     orig_status = (unsigned char)(inp(0x03BA) & 0x80);
  126.  
  127.                     for (i=0; (i<30000) && (!status_changed); ++i)
  128.                         if (orig_status != (unsigned char)/
  129.                                            (inp(0x03BA) & 0x80))
  130.                             status_changed = 1;
  131.  
  132.                     if (status_changed)
  133.                         VideoType = ST_HGC;
  134.                     else
  135.                         VideoType = ST_MDA;
  136.                 }
  137.             }
  138.         }
  139.  
  140.     /* store the segment of video memory */
  141.  
  142.     if ((VideoType == ST_MDA) || (VideoType == ST_HGC))
  143.         BaseAdr = 0xB000;
  144.     else
  145.         BaseAdr = 0xB800;
  146.  
  147.     /* save the original cursor shape */
  148.  
  149.     regs.h.ah = 3;
  150.     regs.h.bh = 0;
  151.  
  152.     int86(0x10,®s,®s);
  153.  
  154.     SavedCursShp = regs.x.cx;
  155.  
  156.     /* and the orihginal cursor position */
  157.  
  158.     regs.h.ah = 3;
  159.     regs.h.bh = 0;
  160.  
  161.     int86(0x10,®s,®s);
  162.  
  163.     SavedCursPos = regs.x.dx;
  164.  
  165.     /* find width of the orginal screen */
  166.  
  167.     regs.h.ah = 0x0F;
  168.     int86(0x10,®s,®s);
  169.  
  170.     Width = (int) regs.h.ah;
  171.  
  172.     /* find length of the original screen */
  173.  
  174.     regs.x.ax = 0x1130;
  175.     regs.h.bh = 0;
  176.     regs.x.dx = 0;
  177.  
  178.     int86(0x10,®s,®s);
  179.  
  180.     Length = regs.x.dx + 1;
  181.  
  182.     if (Length == 1)
  183.         Length = 25;
  184.  
  185.     /* now, allocate a buffer to hold the original
  186.        screen contents... */
  187.  
  188.     SavedScreen = malloc(Length * Width * 2);
  189.  
  190.     /* ...and save the original screen */
  191.  
  192.     if (SavedScreen != NULL)
  193.         for (i = 0; i < Length * Width; i++)
  194.             {
  195.             vmemptr = MK_FP(BaseAdr,i << 1);
  196.             SavedScreen[i] = *vmemptr;
  197.             }
  198.  
  199.     /* make note of the original screen mode */
  200.  
  201.     switch (Width)
  202.         {
  203.         case 40:
  204.             OriginalMode = SM_25x40;
  205.             break;
  206.  
  207.         case 80:
  208.             switch (Length)
  209.                 {
  210.                 case 25:
  211.                     OriginalMode = SM_25x80;
  212.                     break;
  213.                 case 30:
  214.                     OriginalMode = SM_30x80;
  215.                     break;
  216.                 case 43:
  217.                     OriginalMode = SM_43x80;
  218.                     break;
  219.                 case 50:
  220.                     OriginalMode = SM_50x80;
  221.                 }
  222.         }
  223.  
  224.     /* if we have an identifiable screen mode, make it
  225.        the current mode */
  226.  
  227.     if (OriginalMode != -1)
  228.         VideoMode = OriginalMode;
  229.  
  230.     /* mark the cursor as visible */
  231.  
  232.     CursorHidden = 0;
  233.  
  234.     /* get outa here */
  235.  
  236.     return VideoType;
  237.     }
  238.  
  239. void ScrClose()
  240.     {
  241.     int i;
  242.     int far * vmemptr;
  243.  
  244.     /* reset to orginal mode */
  245.  
  246.     if ((OriginalMode != VideoMode) &&/
  247.         (OriginalMode != SM_UNKNOWN))
  248.         ScrSetMode(OriginalMode);
  249.  
  250.     /* restore original screen contents */
  251.  
  252.     if (SavedScreen != NULL)
  253.         for (i = 0; i < Length * Width; i++)
  254.             {
  255.             vmemptr = MK_FP(BaseAdr,i << 1);
  256.             *vmemptr = SavedScreen[i];
  257.             }
  258.  
  259.     /* restore original cursor shape */
  260.  
  261.     regs.h.ah = 1;
  262.     regs.x.cx = SavedCursShp;
  263.  
  264.     int86(0x10,®s,®s);
  265.  
  266.     /* restore original cursor position */
  267.  
  268.     regs.h.ah = 2;
  269.     regs.h.bh = 0;
  270.     regs.x.dx = SavedCursPos;
  271.  
  272.     int86(0x10,®s,®s);
  273.     }
  274.  
  275. int ScrSetMode(ScrMode mode)
  276.     {
  277.     /* don't change to the current mode */
  278.  
  279.     if (VideoMode == mode)
  280.         return 1;
  281.  
  282.     /* if we don't know the type of screen we have,
  283.        don't change mode */
  284.  
  285.     if (OriginalMode == SM_UNKNOWN)
  286.         return 1;
  287.  
  288.     /* make sure the mode requested is valid */
  289.  
  290.     if ((mode < SM_25x40) || (mode > SM_50x80))
  291.         return 0;
  292.  
  293.     /* set modes */
  294.  
  295.     switch (mode)
  296.         {
  297.         case SM_25x40:
  298.             if ((VideoType == ST_MDA) || (VideoType == ST_HGC))
  299.                 return 0;
  300.             else
  301.                 {
  302.                 regs.x.ax = 0x0001;
  303.                 int86(0x10,®s,®s);
  304.  
  305.                 Length = 25;
  306.                 Width  = 40;
  307.                 }
  308.  
  309.             break;
  310.  
  311.         case SM_25x80:
  312.             if ((VideoType == ST_MDA) || (VideoType == ST_HGC))
  313.                 {
  314.                 regs.x.ax = 0x0007;
  315.                 int86(0x10,®s,®s);
  316.                 }
  317.             else /* color */
  318.                 {
  319.                 regs.x.ax = 0x0003;
  320.                 int86(0x10,®s,®s);
  321.  
  322.                 switch (VideoType)
  323.                     {
  324.                     case ST_CGA:
  325.                         regs.x.ax = 0x1112;
  326.                         int86(0x10,®s,®s);
  327.                         break;
  328.  
  329.                     case ST_EGA:
  330.                         regs.x.ax = 0x1111;
  331.                         int86(0x10,®s,®s);
  332.                         break;
  333.  
  334.                     case ST_VGA:
  335.                         regs.x.ax = 0x1114;
  336.